package top.hmtools.controllers;

import javafx.fxml.FXML;
import javafx.scene.Cursor;
import javafx.scene.control.Accordion;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.control.TitledPane;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

import javafx.scene.control.TextArea;

import javafx.scene.layout.AnchorPane;
import javafx.util.Callback;
import top.hmtools.base.StringTools;
import top.hmtools.beans.MapperXmlFileTempletBean;
import top.hmtools.beans.MapperXmlSqlPartGroupBean;
import top.hmtools.beans.MapperXmlSqlPartTempletBean;
import top.hmtools.beans.MapperXmlFileTempletBean;
import top.hmtools.callBacks.MapperXmlFileTempletListCallBack;
import top.hmtools.callBacks.SqlPartTempletListCallBack;
import top.hmtools.commons.AlertUtil;
import top.hmtools.enums.EDBType;
import top.hmtools.model.ResultModel;
import top.hmtools.random.RandomStringTools;
import top.hmtools.system.SystemInfoTools;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;
import javafx.scene.image.ImageView;

public class MapperXmlFileMainPaneController extends BaseController{
	@FXML
	private AnchorPane LeftAnchorPane;
	@FXML
	private TreeView<String> tv_sqlTempletFiles;
	@FXML
	private AnchorPane RightAnchorPane;
	@FXML
	private Button btn_refresh;
	@FXML
	private Button btn_del;
	@FXML
	private Button btn_reset;
	@FXML
	private Button btn_update;
	@FXML
	private Button btn_add;
	@FXML
	private TextField tf_templetName;
	@FXML
	private TextArea tf_comment;
	@FXML
	private TextArea tf_templetContent;
	@FXML
	private TextField tf_id;
	@FXML
	private Accordion accordionLeft;
	@FXML
	private TitledPane tp_mapperXmlFileList;
	@FXML
	private ChoiceBox<String> cb_dbType;
	@FXML
	private ComboBox<String> cb_sqlPartGroup;
	@FXML
	private ComboBox<String> cb_sqlPart;
	@FXML 
	private Button btn_insertSqlGroup;
	@FXML 
	private Button btn_insertSqlPart;
	
	/**
	 * SQL模板文件内容文本域中光标的位置
	 */
	protected int caretPosition;

	// Event Listener on Button[#btn_refresh].onAction
	@FXML
	public void doRefresh(ActionEvent event) {
	    this.initDBType();
	    this.initFileTempletAtLeft();
	    this.initSqlPartGroup();
	}
	// Event Listener on Button[#btn_del].onAction
	@FXML
	public void doDel(ActionEvent event) {
	    String id = this.tf_id.getText();
        if(StringTools.isBlank(id)){
            AlertUtil.showWarnAlert("请选择一条数据");
            return;
        }
        ResultModel result = this.mapperXmlTempletFileManageService.deleteOneByID(id);
        
        initFileTempletAtLeft();
        int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dbType.getValue()));
        this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
        if(result.isStatusSuccess()){
            AlertUtil.showInfoAlert(result.getMessage());
        }else{
            AlertUtil.showErrorAlert(result.getMessage());
        }
	}
	// Event Listener on Button[#btn_reset].onAction
	@FXML
	public void doReset(ActionEvent event) {
		this.tf_comment.setText(null);
		this.tf_templetContent.setText(null);
		this.tf_templetName.setText(null);
	}
	// Event Listener on Button[#btn_update].onAction
	@FXML
	public void doUpdate(ActionEvent event) {
	    String id = this.tf_id.getText();
        if(StringTools.isBlank(id)){
            AlertUtil.showWarnAlert("请选择一条数据");
            return;
        }
        boolean validationInput = this.validationInput();
        if(!validationInput){
            return;
        }
        
        MapperXmlFileTempletBean bean = new MapperXmlFileTempletBean();
        bean.setComment(this.tf_comment.getText());
        bean.setContent(this.tf_templetContent.getText());
        bean.setId(id);
        bean.setName(this.tf_templetName.getText());
        int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dbType.getValue()));
        bean.setDb_type(dbTypecode);
        
        ResultModel result = this.mapperXmlTempletFileManageService.updateOne(bean);
        
        initFileTempletAtLeft();
        this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
        if(result.isStatusSuccess()){
            AlertUtil.showInfoAlert(result.getMessage());
        }else{
            AlertUtil.showErrorAlert(result.getMessage());
        }
	}
	// Event Listener on Button[#btn_add].onAction
	@FXML
	public void doAdd(ActionEvent event) {
		boolean validationInput = this.validationInput();
		if(!validationInput){
			return;
		}
		MapperXmlFileTempletBean bean = new MapperXmlFileTempletBean();
		bean.setComment(this.tf_comment.getText());
		bean.setContent(this.tf_templetContent.getText());
		bean.setId(RandomStringTools.getYyyyMMddHHmmssSSSPrifixInteger(6));
		bean.setName(this.tf_templetName.getText());
		int dbTypecode = EDBType.getTypeCodeByName(String.valueOf(this.cb_dbType.getValue()));
        bean.setDb_type(dbTypecode);
        
		ResultModel result = this.mapperXmlTempletFileManageService.addOne(bean);
		
		initFileTempletAtLeft();
        this.ExpandedPane(EDBType.getByTypeCode(dbTypecode));
		if(result.isStatusSuccess()){
			AlertUtil.showInfoAlert(result.getMessage());
		}else{
			AlertUtil.showErrorAlert(result.getMessage());
		}
	}
	@Override
	public void initialize(URL location, ResourceBundle resources) {
	    this.initDBType();
	    this.initFileTempletAtLeft();
	    this.initSqlPartGroup();
	    
	    //设置SQL模板文件内容文本域失去焦点时获取光标的位置
	    this.tf_templetContent.focusedProperty().addListener(new InvalidationListener() {
			
			@Override
			public void invalidated(Observable observable) {
				caretPosition = tf_templetContent.getCaretPosition();
//				tf_templetContent.appendText(SystemInfoTools.getOSLineSeparator()+String.valueOf(caretPosition)+" "+tf_templetContent.isFocused());//参考代码
			}
		});
	}
	
	/**
	 * 初始化SQL语句片段组别下拉框
	 */
	private void initSqlPartGroup(){
		ObservableList<String> groupItems = this.cb_sqlPartGroup.getItems();
		groupItems.clear();
		
		//组装数据
		ResultModel<MapperXmlSqlPartGroupBean> allSqlPartGroup = this.sqlPartManageService.getAllSqlPartGroup();
		if(allSqlPartGroup.isStatusSuccess()){
			List<MapperXmlSqlPartGroupBean> rows = allSqlPartGroup.getRows(MapperXmlSqlPartGroupBean.class);
			for(int ii=0;rows != null && ii<rows.size();ii++){
				MapperXmlSqlPartGroupBean bean = rows.get(ii);
				groupItems.add(ii,bean.getName());
				if(ii==0){
					this.cb_sqlPartGroup.setValue(bean.getName());
				}
			}
			this.cb_sqlPartGroup.setItems(groupItems);
			this.cb_sqlPartGroup.setUserData(rows);
			
			initSqlPart();//重新初始化SQL语句片段下拉框
		}
		
		//设置数据被选中时的事件（更改SQL语句片段下拉框数据）
		this.cb_sqlPartGroup.getSelectionModel().selectedIndexProperty().addListener(new  InvalidationListener() {
			@Override
			public void invalidated(Observable observable) {
				initSqlPart();//重新初始化SQL语句片段下拉框
			}
		});
		
	}
	
	/**
	 * 初始化SQL语句片段下拉框
	 */
	private void initSqlPart() {
		ObservableList<String> sqlPartItems = this.cb_sqlPart.getItems();
		sqlPartItems.clear();

		// 获取当前选中的数据库
		int dbTypeIndex = this.cb_dbType.getSelectionModel().getSelectedIndex();
		List<EDBType> dbTypes = (List<EDBType>) this.cb_dbType.getUserData();
		EDBType dbType = dbTypes.get(dbTypeIndex);

		// 获取当前选中的SQL片段类别
		int groupIndex = this.cb_sqlPartGroup.getSelectionModel().getSelectedIndex();
		if(groupIndex<0){
			return;
		}
		List<MapperXmlSqlPartGroupBean> groups = (List<MapperXmlSqlPartGroupBean>) this.cb_sqlPartGroup.getUserData();
		MapperXmlSqlPartGroupBean partGroupBean = groups.get(groupIndex);

		// 填充数据
		ResultModel<MapperXmlSqlPartTempletBean> sqlPartTempletBeansDB = this.sqlPartManageService
				.getSqlPartTempletsByCondition(dbType.getTypeCode(), partGroupBean.getId());
		if (sqlPartTempletBeansDB.isStatusSuccess()) {
			List<MapperXmlSqlPartTempletBean> rows = sqlPartTempletBeansDB.getRows();
			for (int ii = 0; rows != null && ii < rows.size(); ii++) {
				MapperXmlSqlPartTempletBean bean = rows.get(ii);
				sqlPartItems.add(ii, bean.getName());
				if (ii == 0) {
					this.cb_sqlPart.setValue(bean.getName());
				}
			}
			this.cb_sqlPart.setItems(sqlPartItems);
			this.cb_sqlPart.setUserData(rows);
		}

	}
	
	/**
     * 初始化数据库类型下拉框
    * 方法说明：                    initDataType
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
	private void initDBType() {
		this.cb_dbType.getItems().clear();
		ObservableList<String> dbTypes = FXCollections.observableArrayList();
		List<EDBType> list = new ArrayList<>();// 存储原始数据集
		int index = 0;
		for (EDBType item : EDBType.values()) {
			String name = item.getName();
			dbTypes.add(index, name);// 使选则列表项的索引与原始数据同步
			list.add(index, item);// 使选则列表项的索引与原始数据同步
			if (index == 0) {
				this.cb_dbType.setValue(name);
			}
			index++;
		}
		this.cb_dbType.setUserData(list);
		this.cb_dbType.setItems(dbTypes);

		// 设置数据被选中时的事件（更改SQL语句片段下拉框数据）
		this.cb_dbType.getSelectionModel().selectedIndexProperty().addListener(new InvalidationListener() {
			@Override
			public void invalidated(Observable observable) {
				initSqlPart();// 重新初始化SQL语句片段下拉框
			}
		});
	}
	
    /**
     * 初始化窗口左边折叠面板
    * 方法说明：                    initFileTempletAtLeft
    * 输入参数说明：           
    * 输出参数说明：           void
    *
    *
     */
	private void initFileTempletAtLeft(){
	    //情况折叠面板
	    this.accordionLeft.getPanes().clear();
	    
	  //遍历数据库类别
        for(EDBType item:EDBType.values()){
            //获取类别名称及内容数据，并初始化 TitledPane 折叠面板
            String name = item.getName();
            TreeView< String> treeView = new TreeView<>();
            treeView.setRoot(new TreeItem<>());
            treeView.setShowRoot(false);
            
            Callback<TreeView<String>, TreeCell<String>> defaultCellFactory =  TextFieldTreeCell.forTreeView();
            treeView.setCellFactory(new MapperXmlFileTempletListCallBack(defaultCellFactory,this.tf_id,this.tf_templetName,this.cb_dbType,this.tf_templetContent,this.tf_comment));
            
            ResultModel resultModel = this.mapperXmlTempletFileManageService.getSqlPartTempletsByDataType(item.getTypeCode());
            if(resultModel.isStatusSuccess()){
                List<MapperXmlFileTempletBean> rows = resultModel.getRows();
                for(int ii=0;rows != null &&ii<rows.size();ii++){
                    MapperXmlFileTempletBean bean = rows.get(ii);
                    TreeItem<String> tItem = new TreeItem<String>();
                    tItem.setValue(bean.getName());
                    ImageView icon = new ImageView("images/file.png");
                    icon.setFitHeight(16);
                    icon.setFitWidth(16);
                    icon.setUserData(bean);
                    tItem.setGraphic(icon);
                    tItem.setGraphic(icon);
                    
                    treeView.getRoot().getChildren().add(tItem);
                }
            }
            
            TitledPane titledPane = new TitledPane(name,treeView);
            this.accordionLeft.getPanes().add(titledPane);
        }
	}
	
	/**
     * 展开指定的折叠面板
    * 方法说明：                    ExpandedPane
    * 输入参数说明：           @param edbType
    * 输出参数说明：           void
    *
    *
     */
    private void ExpandedPane(EDBType edbType){
        ObservableList<TitledPane> panes = this.accordionLeft.getPanes();
        for(TitledPane item:panes){
            String text = item.getText();
            if(edbType.getName().equals(text)){
                item.setExpanded(true);
            }
        }
    }
	
	/**
	 * 验证入参
	 * @return
	 */
	private boolean validationInput(){
		String name = this.tf_templetName.getText();
		if(StringTools.isBlank(name)){
			AlertUtil.showWarnAlert("模板名称不能为空");
			return false;
		}
		String content = this.tf_templetContent.getText();
		if(StringTools.isBlank(content)){
			AlertUtil.showWarnAlert("模板内容不能为空");
			return false;
		}
		return true;
	}

	@FXML
	public void doInsertSqlGroup(ActionEvent event) {
		int groupIndex = this.cb_sqlPartGroup.getSelectionModel().getSelectedIndex();
		if(groupIndex<0){
			return;
		}
		List<MapperXmlSqlPartGroupBean> groups = (List<MapperXmlSqlPartGroupBean>) this.cb_sqlPartGroup.getUserData();
		MapperXmlSqlPartGroupBean partGroupBean = groups.get(groupIndex);
		//${userName!}
		String factor = "${"+partGroupBean.getFactor_name()+"!}";
		tf_templetContent.insertText(caretPosition, factor);
	}

	@FXML
	public void doInsertSqlPart(ActionEvent event) {
		int index = cb_sqlPart.getSelectionModel().getSelectedIndex();
		if (index < 0) {
			return;
		}
		List<MapperXmlSqlPartTempletBean> sqlPartTempletBeans = (List<MapperXmlSqlPartTempletBean>) cb_sqlPart.getUserData();
		MapperXmlSqlPartTempletBean partTempletBean = sqlPartTempletBeans.get(index);
		// ${userName!}
		String factor = "${" + partTempletBean.getFactor_name() + "!}";
		tf_templetContent.insertText(caretPosition, factor);
	}
	
}
